#include "chatRoom.h"
#include "stdShared.h"
#include "ClientSingle.h"
#include <sqlite3.h>

unordered_map<string, int> UsernameToConnfd; // connfd与用户名映射表
unordered_map<int, string> ConnfdToUsername;

ChatRoom::ChatRoom(const StdTcpSocketPtr &client) : m_clientInfo(client)
{
    /* 连接数据库 */
    SQliteDataBase::getInstance().connectDB("./music.db");

    /* 创建数据库表 : 数据库存在则不创建 */
    const char *sql = "CREATE TABLE IF NOT EXISTS userInfo(username text not null, passwd text not null);";
    SQliteDataBase::getInstance().executeSql(sql);
}

ChatRoom::~ChatRoom()
{
    // 不用关闭数据库，单例析构时候会关闭数据库
}

void ChatRoom::handleRegisterInfo(const string &msg)    //一个客户端和服务器的通信，用不到客户端单例，但是要姓名和客户端只能指针进行绑定
{
    
/* 从客户端接收数据 */
    /* 1.将json字符串解析为json对象 */
    json_object *jsonObj = json_tokener_parse(msg.c_str());
    /* 2.根据key得到value */
    string name = json_object_get_string(json_object_object_get(jsonObj, "name"));
    string passwd = json_object_get_string(json_object_object_get(jsonObj, "passwd"));
    cout << name <<  " 用户正在注册..." << endl;
    /* 3.销毁json对象 */
    json_object_put(jsonObj);

/* 给客户端发送数据 */
    /* 1.创建json对象 */
    json_object *resObj = json_object_new_object();
    /* 2.向json对象添加<key, value>键值对 */
    json_object_object_add(resObj, "type", json_object_new_int(REGISTER));

    /* 先判断用户是否存在 */
    if (userIsExist(name))
    { // 已存在，发送status
        json_object_object_add(resObj, "status", json_object_new_int(REGISTER_EXIST_USER));
    }
    else
    {   // 不存在，发送status，将用户信息保存至数据库
        int connfd = m_clientInfo->getSockAttr()->connfd; // 获取客户端的connfd
        saveUserInfo(name, passwd);
        json_object_object_add(resObj, "status", json_object_new_int(REGISTER_SUCCESS));

        //!/* 添加用户到 map容器中 */
        ClientSingle *clientMap = ClientSingle::getInstance();
        clientMap->InsertClientInfo(name, m_clientInfo);

        // 将 connfd 与用户名关联
        UsernameToConnfd[name] = connfd;
        ConnfdToUsername[connfd] = name;
    }

    /* 3.json对象转为字符串发送出去 */
    const char *resStr = json_object_to_json_string(resObj);
    m_clientInfo->sendMessage(resStr);
}

void ChatRoom::handleLoginInfo(const string &msg)
{
/* 从客户端接收数据 */
    /* 1.将json字符串解析为json对象 */
    json_object *jsonObj = json_tokener_parse(msg.c_str());

    /* 2.根据key得到value */
    string name = json_object_get_string(json_object_object_get(jsonObj, "name"));
    string passwd = json_object_get_string(json_object_object_get(jsonObj, "passwd"));
    cout << name << " 用户正在登录... " << endl;
    int connfd = m_clientInfo->getSockAttr()->connfd; // 获取客户端的connfd
    

    /* 3.销毁json对象 */
    json_object_put(jsonObj);

/* 给客户端发送数据 */
    json_object *resObj = json_object_new_object();
    json_object_object_add(resObj, "type", json_object_new_int(LOGIN));

    // 判断用户名及密码是否匹配
    if (userIsRight(name, passwd) == 0)
    {
        json_object_object_add(resObj, "status", json_object_new_int(LOGIN_SUCCESS));
        //!/* 添加用户到 map容器中 */
        ClientSingle *clientMap = ClientSingle::getInstance();
        clientMap->InsertClientInfo(name, m_clientInfo);

        // 将 connfd 与用户名关联
        UsernameToConnfd[name] = connfd;
        ConnfdToUsername[connfd] = name;
    }
    else if ((userIsRight(name, passwd) == 1))
    {
        json_object_object_add(jsonObj, "status", json_object_new_int(LOGIN_NO_USER));
    }
    else
    {
        json_object_object_add(jsonObj, "status", json_object_new_int(LOGIN_PASSED_ERROR));
    }
    
    const char *resStr = json_object_to_json_string(resObj);
    m_clientInfo->sendMessage(resStr);
}

void ChatRoom::handleFriendRequest(const string &msg)
{

/* 接收好友申请消息,解析目标客户端clientInfo */
    json_object *jsonObj = json_tokener_parse(msg.c_str());

    string destName = json_object_get_string(json_object_object_get(jsonObj, "destName"));
    string srcName = ConnfdToUsername[m_clientInfo->getSockAttr()->connfd];
 
    cout << srcName << "向" << destName << "发送好友申请" << endl;

#if 0
    int destFriendConnfd = UsernameToConnfd[destName];
    json_object *reqObj = json_object_new_object();
    json_object_object_add(reqObj, "type", json_object_new_int(FRIEND_REQUEST));
    json_object_object_add(reqObj, "srcName", json_object_new_string(srcName.c_str()));
    
    const char *reqStr = json_object_to_json_string(reqObj);
    int sendMessageBytes = m_clientInfo->sendMessage(destFriendConnfd, reqStr, strlen(reqStr));
#else
    /* 取出对应用户的通信句柄 */
    ClientSingle *clientMap = ClientSingle::getInstance();
    StdTcpSocketPtr destFriend = clientMap->GetTargetClientInfo(destName);

    json_object *reqObj = json_object_new_object();
    json_object_object_add(reqObj, "type", json_object_new_int(FRIEND_REQUEST));
    json_object_object_add(reqObj, "srcName", json_object_new_string(srcName.c_str()));

    const char *reqStr = json_object_to_json_string(reqObj);
    int sendMessageBytes = destFriend->sendMessage(reqStr, strlen(reqStr));

    // 反馈给发送好友请求的用户
    // if(sendMessageBytes != -1)
    // {
    //     string str = "对" + destName + "的好友请求已发送！";
    //     m_clientInfo->sendMessage(m_clientInfo->getSockAttr()->connfd, str.c_str(), strlen(str.c_str()));
    // }
#endif
    /* 接收反馈结果发送给申请好友的用户 */
    // string recvmsg;
    // m_clientInfo->recvMessage(recvmsg);
    // cout << "接收到的反馈结果" << recvmsg << endl;
    // json_object *recvJsonObj = json_tokener_parse(recvmsg.c_str());
    // int type = json_object_get_int(json_object_object_get(recvJsonObj, "type"));

    // m_clientInfo->sendMessage(m_clientInfo->getSockAttr()->connfd, recvmsg.c_str(), strlen(recvmsg.c_str()));
    // m_clientInfo->sendMessage(recvmsg.c_str(), strlen(recvmsg.c_str()));

    // cout << "原客户端信息发送成功" << endl;

    // json_object_put(recvJsonObj); // 销毁接收到的JSON对象

    json_object_put(jsonObj);
    json_object_put(reqObj); // 销毁好友申请JSON对象
}

void ChatRoom::handleFriendResult(const string &msg)
{
    /* 接收好友申请结果并发送给申请的用户 */
    cout << "接收到的反馈结果" << msg << endl;
    
    json_object *jsonObj = json_tokener_parse(msg.c_str());
    string srcName = json_object_get_string(json_object_object_get(jsonObj, "srcName"));
    int status = json_object_get_int(json_object_object_get(jsonObj, "status"));
    json_object_put(jsonObj);

    string destName = ConnfdToUsername[m_clientInfo->getSockAttr()->connfd];
    /* 取出对应用户的通信句柄 */
    ClientSingle *clientMap = ClientSingle::getInstance();
    StdTcpSocketPtr srcFriend = clientMap->GetTargetClientInfo(srcName);
    
    json_object *sendObj = json_object_new_object();
    json_object_object_add(sendObj, "type", json_object_new_int(FRIEND_RESULT));
    json_object_object_add(sendObj, "destName", json_object_new_string(destName.c_str()));
    json_object_object_add(sendObj, "status", json_object_new_int(status));

    const char *sendmsg = json_object_to_json_string(sendObj);
    // 将反馈结果发送给申请好友的用户
    int sendMessageBytes = srcFriend->sendMessage(sendmsg);
    if(sendMessageBytes > 0)
    {
        cout << "sendMessage success" << endl;
    }
    cout << "发出的的反馈结果" << sendmsg << endl;
} 

/* 判断用户是否已存在 */
bool ChatRoom::userIsExist(const string &name)
{
    // 也可以格式化转
    // const char * sql = "select count(1) from userInfo where username = '%s';";
    // char requestSql[BUFFER_SIZE] = { 0 };
    // snprintf(requestSql, BUFFER_SIZE, sql, name.c_str());

    string sql = "select count(1) from userInfo where username ='" + name + "';";
    QueryResult res = SQliteDataBase::getInstance().querySql(sql);
    return res.rows[0][0] != "0";
}

int ChatRoom::userIsRight(const string &name, const string &passwd)
{
    /* 判断用户名 */
    string sql = "SELECT count(1) FROM userInfo WHERE username = '" + name + "';";
    QueryResult res = SQliteDataBase::getInstance().querySql(sql); // 不为零则用户存在
    if (res.rows[0][0] == "0")
    {
        cout << "账户不存在" << endl;
        return 1;
    }

    /* 判断密码 */
    sql = "SELECT count(1) FROM userInfo WHERE username = '" + name + "' AND passwd = '" + passwd + "';";
    res = SQliteDataBase::getInstance().querySql(sql); // 不为零则用户存在
    if (res.rows[0][0] == "0")
    {
        cout << "密码错误" << endl;
        return 2;
    }
    return 0;
}

/* 储存用户信息 */
bool ChatRoom::saveUserInfo(const string &name, const string &passwd)
{
    const char *sql = "INSERT INTO userInfo(username, passwd) VALUES('%s', '%s');";
    char requestSql[BUFFER_SIZE] = {0};
    snprintf(requestSql, BUFFER_SIZE, sql, name.c_str(), passwd.c_str());

    return SQliteDataBase::getInstance().executeSql(requestSql);
}
